package modele;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.UserTransaction;

import org.apache.commons.mail.HtmlEmail;

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class FacadeMembre {

	@PersistenceContext
	private EntityManager em;
	@Resource private UserTransaction ut;
	
	
	public Membre connexion(String id, String mdp){
		
		
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Membre> criteria = builder.createQuery( Membre.class );
		Root<Membre> membreRoot = criteria.from( Membre.class );
		//Metamodel m = em.getMetamodel();
		//EntityType<Membre> Membre_ = m.entity(Membre.class);
		criteria.select( membreRoot );
		Predicate condition = builder.equal( membreRoot.get("mail"), id );
		Predicate condition2 =  builder.equal( membreRoot.get("password"), mdp ) ;
		Predicate condition3 =  builder.and(condition, condition2) ;
		
		// On verifie que le compte associé a l'utilisateur est bien 
		// activé
		Predicate condition4 =  builder.equal(membreRoot.get("active"), true) ;
		
		criteria.where( builder.and(condition3, condition4) );
		List<Membre> resultat = em.createQuery( criteria ).getResultList();
		
		if(resultat.size() == 1){
			return resultat.get(0);
		}
		else{
			return null;
		}
	}
	
	public boolean inscription(Membre m){
		
		boolean estExisantant = false;
		
		// test la presence de l'adresse email dans la base afin de 
		// savoire si un membre est deja inscrit
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Membre> criteria = builder.createQuery( Membre.class );
		Root<Membre> membreRoot = criteria.from( Membre.class );
		
		criteria.select( membreRoot );
		Predicate condition = builder.equal( membreRoot.get("mail"), m.getMail() );
		
		criteria.where( condition );
		List<Membre> resultat = em.createQuery( criteria ).getResultList();
		
		if(resultat.size() == 1){
			estExisantant = true;
		}
		else{
			estExisantant = false;
		}
		
		// si l'adresse email est deja dans la base on renvoie false 
		// pour signaler une erreur
		if(estExisantant){
			return false;
		}
		else{ // on enregistre le nouvel inscrit
			try {
				ut.begin();
				
				// le compte n'est pas activé au depart
				m.setActive(false);
				// genetration d'une clé associé au compte
				m.setCle(AeSimpleMD5.MD5(String.valueOf(System.currentTimeMillis()*10000)));
				em.persist(m);
				
				// Envoie du mail de confirmation contenant un lien 
				// pour pouvoir activer le compte
				HtmlEmail email = new HtmlEmail();
				//email.setHostName("smtp.gmail.com");
				email.setHostName("mail.enseeiht.fr");
				//email.setSmtpPort(25);
				//email.setSmtpPort(587);
				//email.setAuthenticator(new DefaultAuthenticator("strategien7@gmail.com", "brulhart"));
				email.setTLS(true);
				email.setFrom("inscription@site.com");
				email.setSubject("Site.com Activation de votre compte");
				email.setHtmlMsg("<html>" +
						"<p>Bienvenu sur <strong>site.com</strong></p>" +
						"<p>"+
							"Pour active votre compte cliquez sur le lien suivant :" +
							"<a href='http://localhost:8080/WebSite/Compte?page=activation&id=" + 
								m.getId() +
								"&cle=" +
								m.getCle() +
								"' >Activer mon compte</a>" +
						"</p>" +
						"</html>");
				email.addTo(m.getMail());
				email.send();
		
				
				ut.commit();
				
			} catch (Exception e) {
				try {
					ut.rollback();
				} catch (Exception e1) {
					e1.printStackTrace();
				} 
			}
			
			return true;
		}
		
		
	}
	
	public void modificationCompte(Membre m) {
		try {
			ut.begin();
			em.merge(m);
			ut.commit();
		} catch (Exception e) {
			try{
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			} 
		}
	}
	
	public boolean activation(long id, String cle){
		
		Membre m = em.find(Membre.class, id);
				
		if(m.getCle().equals(cle)){
			try {
				ut.begin();
				m.setActive(true);
				em.merge(m);
				ut.commit();
			} catch (Exception e) {
				try{
					ut.rollback();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			
			
			return true;
		}
		else{
			return false;
		}
	}
	
	public Membre majMembre(Long idmembre){
		Membre m = null;
		m=em.find(Membre.class, idmembre);
		return m;
	}
	
	public ArrayList<Membre> getClassementMembres(){
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Membre> criteria = builder.createQuery( Membre.class );
		Root<Membre> menuRoot = criteria.from( Membre.class );
		criteria.select(menuRoot);
		ArrayList<Membre> list = (ArrayList<Membre>) em.createQuery(criteria).getResultList();
		Collections.sort(list,new ComparatorMembrePoints());
		return list;		
	}
	
	public ArrayList<Notification> getDernieresNotifications(Long id,int offset,int i){
		Membre m=em.find(Membre.class, id);
		List<Notification> liste = (List<Notification>) m.lireNotifications();
		ArrayList<Notification> res = new ArrayList<Notification>();
		Collections.sort(liste,new ComparatorNotificationDate());
		for(int j=offset;j<Math.min(offset+i+1,liste.size());j++){
				res.add(liste.get(j));
		}
		try {
			ut.begin();
			em.merge(m);
			ut.commit();
		} catch (Exception e) {
			try{
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			} 
		}
		return res;
	}
		
		

	
}
